﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;



namespace Huanan.Algorithm.DSP
{
    public static class ECGAlgHelper
    {
        // FindAllHeartBeats、GetECGHeartBeatInfoOfAllLeads 的 C# 封装最多支持 18 个导联。
        const int MaxLeadCount = 20;

        public static string GetPAxisString(this ECGParameters ecgParameters, ECGHeartBeatInfoVector ehbiv, string invalidValue)
        {
            if (ecgParameters == null)
                throw new ArgumentNullException("ecgParameters");

            if (ehbiv == null)
                throw new ArgumentNullException("ehbiv");

            if (ehbiv[0].HasPSegment())
                return ecgParameters.PAxis.ToString();
            else
                return invalidValue;
        }

        public static string GetQRSAxisString(this ECGParameters ecgParameters)
        {
            if (ecgParameters == null)
                throw new ArgumentNullException("ecgParameters");

            return ecgParameters.QRSAxis.ToString();
        }

        public static string GetTAxisString(this ECGParameters ecgParameters, ECGHeartBeatInfoVector ehbiv, string invalidValue)
        {
            if (ecgParameters == null)
                throw new ArgumentNullException("ecgParameters");

            if (ehbiv == null)
                throw new ArgumentNullException("ehbiv");

            if (ehbiv[0].HasTSegment())
                return ecgParameters.TAxis.ToString();
            else
                return invalidValue;
        }

        public static uint FindAllHeartBeats(HeartBeatInfoVector heartBeatInfoVector, int longLead, params double[][] leads)
        {
            if (heartBeatInfoVector == null || leads == null)
                throw new ArgumentNullException();

            if (longLead < 0 || longLead >= leads.Length || leads.Length > MaxLeadCount || !AllDimsTheSameSize(leads) || leads[0] == null)
                throw new ArgumentException();

            var all18Leads = To18Lead(leads);

            return HNAlgoNative.FindAllHeartBeats(heartBeatInfoVector, longLead, leads[0].Length,
                all18Leads[0],
                all18Leads[1],
                all18Leads[2],
                all18Leads[3],
                all18Leads[4],
                all18Leads[5],
                all18Leads[6],
                all18Leads[7],
                all18Leads[8],
                all18Leads[9],
                all18Leads[10],
                all18Leads[11],
                all18Leads[12],
                all18Leads[13],
                all18Leads[14],
                all18Leads[15],
                all18Leads[16],
                all18Leads[17]);
        }

        public static bool GetECGHeartBeatInfoOfAllLeads(ECGHeartBeatInfoVector hbiOfAllLeads, HeartBeatInfoVector hbiv, int heartBeatID, params double[][] leads)
        {
            if (hbiOfAllLeads == null || hbiv == null || leads == null)
                throw new ArgumentNullException();

            if (hbiv.Count == 0 || heartBeatID < 0 || heartBeatID >= hbiv.Count || !AllDimsTheSameSize(leads) || leads[0] == null)
                throw new ArgumentException();

            var all18Leads = To18Lead(leads);

            return HNAlgoNative.GetECGHeartBeatInfoOfAllLeads(hbiOfAllLeads, hbiv, heartBeatID,
                leads[0].Length,
                all18Leads[0],
                all18Leads[1],
                all18Leads[2],
                all18Leads[3],
                all18Leads[4],
                all18Leads[5],
                all18Leads[6],
                all18Leads[7],
                all18Leads[8],
                all18Leads[9],
                all18Leads[10],
                all18Leads[11],
                all18Leads[12],
                all18Leads[13],
                all18Leads[14],
                all18Leads[15],
                all18Leads[16],
                all18Leads[17]);
        }

        internal static bool AllDimsTheSameSize(double[][] data)
        {
            if (data == null || data.Length == 0)
                return true;

            if (data[0] == null)
            {
                for (int i = 1; i < data.Length; ++i)
                    if (data[i] != null)
                        return false;

                return true;
            }
            else
            {
                int dataLength = data[0].Length;
                for (int i = 1; i < data.Length; ++i)
                    if (data[i] == null || data[i].Length != dataLength)
                        return false;

                return true;
            }
        }

        internal static double[][] To18Lead(params double[][] leads)
        {
            if (leads == null || leads.Length == 0 || leads.Length > MaxLeadCount || !AllDimsTheSameSize(leads))
                throw new ArgumentException();

            double[][] all18Leads = new double[MaxLeadCount][];
            for (int i = 0; i < MaxLeadCount; ++i)
            {
                if (i < leads.Length)
                    all18Leads[i] = leads[i];
                else
                    all18Leads[i] = null;
            }

            return all18Leads;
        }
    }
}

